#include "gpio_pwm.h"
#include <cstdio>
#include <cstring>
#include <cstdlib>
extern "C"{
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
}

using namespace std;

int gpio_pwm::gpio_config(const char *attr, const char *val)
{
    char file_path[100];
    int len;
    int fd;

    sprintf(file_path, "%s/%s", gpio_path, attr);
    if (0 > (fd = open(file_path, O_WRONLY))) {
        perror("open error");
        return fd;
    }

    len = strlen(val);
    if (len != write(fd, val, len)) {
        perror("write error");
        close(fd);
        return -1;
    }

    close(fd);  //关闭文件
    return 0;
}

gpio_pwm::gpio_pwm(QObject *parent, qint8 gpio_sec, qint64 period, qint64 duty) : QObject(parent)
{
    this->duty = duty;
    this->period = period;

    /* 判断指定编号的GPIO是否导出 */
     sprintf(gpio_path, "/sys/class/gpio/gpio%u", gpio_sec);

     if (access(gpio_path, F_OK)) {//如果目录不存在 则需要导出

         int fd;
         int len;

         if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
             perror("open error");
             exit(-1);
         }

         len = strlen(QString::number(gpio_sec).toLatin1().data());
         if (len != write(fd, QString::number(gpio_sec).toLatin1().data(), len)) {//导出gpio
             perror("write error");
             close(fd);
             exit(-1);
         }

         close(fd);  //关闭文件
     }
     /* 配置为输出模式 */
     if (gpio_config("direction", "out"))
         printf("gpio config out err\n");

     /* 极性设置 */
     if (gpio_config("active_low", "0"))
         printf("gpio config active_low err\n");

     /* 控制GPIO输出高低电平 */
     if (gpio_config("value", "1"))
         printf("gpio config out val err\n");

     /* 创建并启动PWM输出线程 */
     this->thread = new gpio_pwm_thread();
     this->thread->set_period(period);
     this->thread->set_duty(duty);
     this->thread->start();

     /* 关联信号与槽 */
     connect(this->thread,&gpio_pwm_thread::duty_time_out,this,&gpio_pwm::duty_time_out_slots);
     connect(this->thread,&gpio_pwm_thread::period_time_out,this,&gpio_pwm::period_time_out_slots);
}

gpio_pwm::~gpio_pwm()
{
    this->thread->set_pwm_out(false);
    this->thread->set_pwm_exist(false);
}

/**
  @description:设置pwm输出的占空比
  @param - duty:占空比
*/
void gpio_pwm::set_duty(qint64 duty)
{
    this->duty = duty;
    this->thread->set_duty(duty);
}

/* 停止输出PWM */
void gpio_pwm::pwm_out_stop()
{
    this->thread->set_pwm_out(false);
}

/* 开始输出PWM */
void gpio_pwm::pwm_out_start()
{
this->thread->set_pwm_out(true);
}

/* 获取占空比 */
qint64 gpio_pwm::get_duty()
{
    return this->duty;
}

/* 获取周期 */
qint64 gpio_pwm::get_period()
{
    return this->period;
}

void gpio_pwm::duty_time_out_slots()
{
    this->gpio_config("value","0");
}

void gpio_pwm::period_time_out_slots()
{
    this->gpio_config("value","1");
}
